#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    configFileInit();
    ui->lineEditHost->setText(init_server_ip);
    ui->lineEditPort->setText(init_server_port);
    ui->lineEditClientId->setText(init_clientid);
    ui->lineEditTopic->setText(init_subscribe_topic);
    ui->lineEditPuslishTopic->setText(init_publish_topic);

    //（文本编辑框为空时）提示内容
    ui->lineEditHost->setPlaceholderText("服务器域名/IP");
    ui->lineEditPort->setPlaceholderText("服务器端口");
    ui->lineEditClientId->setPlaceholderText("clientid");
    ui->lineEditTopic->setPlaceholderText("订阅的topic");
    ui->lineEditPuslishTopic->setPlaceholderText("推送消息的topic");
    ui->lineEditMessage->setPlaceholderText("推送消息的内容");


    mqttClient = new QMqttClient();
    //stateChanged信号，mqtt连接状态改变时触发
    connect(mqttClient, &QMqttClient::stateChanged, this, &MainWindow::stateChangedSlot);

    connect(mqttClient, &QMqttClient::errorChanged, this, &MainWindow::errorChangedSlot);
    connect(mqttClient, &QMqttClient::messageReceived, this, &MainWindow::messageReceivedSlot);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::closeEvent ( QCloseEvent * e )
{
    QSettings *configIniWrite = new QSettings(CONFIG_FILE_PATH_DEFAULT, QSettings::IniFormat);
    //向ini文件中写入内容,setValue函数的两个参数是键值对

    configIniWrite->setValue("server_port", ui->lineEditPort->text().toInt());
    configIniWrite->setValue("server_ip", ui->lineEditHost->text().trimmed());
    configIniWrite->setValue("clientid", ui->lineEditClientId->text().trimmed());
    configIniWrite->setValue("user", "user");
    configIniWrite->setValue("passwd", "");
    configIniWrite->setValue("publish_topic", ui->lineEditPuslishTopic->text().trimmed());
    configIniWrite->setValue("subscribe_topic", ui->lineEditTopic->text().trimmed());

    //写入完成后删除指针
    delete configIniWrite;

    e->accept();//不会将事件传递给组件的父组件


}

void MainWindow::configFileInit()
{

    if (!configFile.exists(CONFIG_FILE_PATH_DEFAULT))
    {
        qDebug()<<"no config.ini, need create";

       //Qt中使用QSettings类读写ini文件
       //QSettings构造函数的第一个参数是ini文件的路径,第二个参数表示针对ini文件,第三个参数可以缺省
       QSettings *configIniWrite = new QSettings(CONFIG_FILE_PATH_DEFAULT, QSettings::IniFormat);
       //向ini文件中写入内容,setValue函数的两个参数是键值对
       //向ini文件的第一个节写入内容,ip节下的第一个参数
       configIniWrite->setValue("server_ip", "broker.emqx.io");
       //向ini文件的第一个节写入内容,ip节下的第二个参数
       configIniWrite->setValue("server_port", "1883");
       //向ini文件的第二个节写入内容,port节下的第一个参数
       configIniWrite->setValue("clientid", "qtmqtt_");
       configIniWrite->setValue("user", "user");
       configIniWrite->setValue("passwd", "");
       configIniWrite->setValue("publish_topic", "/topic/publish");
       configIniWrite->setValue("subscribe_topic", "/topic/subscribe");
       //写入完成后删除指针
       delete configIniWrite;

    }


    {
        QSettings *configIniRead = new QSettings(CONFIG_FILE_PATH_DEFAULT, QSettings::IniFormat);
           //将读取到的ini文件保存在QString中，先取值，然后通过toString()函数转换成QString类型
           init_server_ip = configIniRead->value("server_ip").toString();
           init_server_port = configIniRead->value("server_port").toString();
           init_clientid = configIniRead->value("clientid").toString();
           init_username = configIniRead->value("username").toString();
           init_passwd = configIniRead->value("passwd").toString();
           init_publish_topic = configIniRead->value("publish_topic").toString();
           init_subscribe_topic = configIniRead->value("subscribe_topic").toString();

           if(init_clientid == "qtmqtt_")
           {
               QTime currentTime=QTime::currentTime();
               init_clientid = QString("qtmqtt_%1_%2").arg(currentTime.hour()*10000 + currentTime.minute()*100 + currentTime.second()).arg(currentTime.msec());
                //init_clientid=QString("qtmqtt_" + QString(QTime::currentTime()));
                qDebug()<<"use clientid template: " + init_clientid <<endl;
           }
           else
           {
                qDebug()<<"use user clientid:" + init_clientid<<endl;
           }

           //读入入完成后删除指针
           delete configIniRead;
    }

}

void MainWindow::initMqttClinet()
{
    mqttClient->setHostname(ui->lineEditHost->text().trimmed());
    mqttClient->setPort(ui->lineEditPort->text().toInt());
    mqttClient->setProtocolVersion(QMqttClient::MQTT_3_1_1);
    mqttClient->setClientId(ui->lineEditClientId->text().trimmed());
    mqttClient->setUsername("admin");
    mqttClient->setPassword("password");

    mqttClient->connectToHost();
}

void MainWindow::disconnectMqttClinet()
{

    mqttClient->disconnectFromHost();
}


void MainWindow::on_pBtn_Connect_clicked()
{

    if(connect_flag==0) //now disconnect status, run connect
    {
        initMqttClinet();
    }
    else if(connect_flag==2) //now connect status, run disconnect
    {
        disconnectMqttClinet();
    }


}

void MainWindow::stateChangedSlot(QMqttClient::ClientState state)
{
    QString info("");
    if(state == 0)
    {
        connect_flag=0;
        ui->pBtn_Connect->setText("连接");
        info = QString("mqtt disconnected. error:%1" ).arg(mqttClient->error());
    }
    else if(state == 1)
    {
        info = "mqtt connecting";
    }
    else if(state == 2)
    {
        connect_flag=2;
        ui->pBtn_Connect->setText("断开");
        info = QString("mqtt connected. hostname:%1").arg(mqttClient->hostname());
    }
    ui->editLog->insertPlainText(QTime::currentTime().toString()
                                 + QString("state:%1 info:%2\n").arg(state).arg(info));
}

void MainWindow::errorChangedSlot(QMqttClient::ClientError error)
{
    QString errorCode;
    switch(error)
    {
        case QMqttClient::TransportInvalid:
            errorCode="TransportInvalid";
        break;
        case QMqttClient::NoError:
            errorCode="NoError";
        break;
        default:
            errorCode="value:" + QString::number(error);
        break;
    }

    qDebug()<<__FILE__<<__LINE__<<errorCode;

    ui->editLog->insertPlainText(QString("error:%1\n").arg(errorCode));
}

void MainWindow::messageReceivedSlot(const QByteArray &message, const QMqttTopicName &topic)
{
    qDebug()<<__FILE__<<__LINE__<<message<<topic;

    const QString content = QTime::currentTime().toString()
                + QLatin1String(" Received Topic: ")
                + topic.name()
                + QLatin1String(" Message: ")
                + message
                + QLatin1Char('\n');
    ui->editLog->insertPlainText(content);
}

void MainWindow::on_pBtn_Publish_clicked() // 发布
{
    if(mqttClient == nullptr)
    {
        ui->editLog->insertPlainText(QString("[Error] Before publish, Please init mqtt client.\n"));
        return;
    }
    if (mqttClient->publish(ui->lineEditPuslishTopic->text(),ui->lineEditMessage->text().toUtf8()) == -1)
    {
        ui->editLog->insertPlainText(QString("[Error] Could not publish message.\n"));
    }
    ui->editLog->insertPlainText(QString("[Info] Already try publish msg:"
                                         + ui->lineEditPuslishTopic->text())
                                         + ",\""
                                         + ui->lineEditMessage->text().toUtf8()
                                         + "\"\n");
}

void MainWindow::on_pBtn_Subscribe_clicked() // 订阅
{
    if(mqttClient == nullptr)
    {
        ui->editLog->insertPlainText(QString("[Error]  Before subscribe, Please init mqtt client.\n"));
        return;
    }
    auto subscription = mqttClient->subscribe(ui->lineEditTopic->text());
    if (!subscription) {
        ui->editLog->insertPlainText(QString("[Error] Could not subscribe. Is there a valid connection?\n"));
        return;
    }
    ui->editLog->insertPlainText(QString("[Info] Already try subscribe:" + ui->lineEditTopic->text()) + "\n");
}

void MainWindow::on_pBtn_Ping_clicked()
{
    if(mqttClient == nullptr)
    {
        ui->editLog->insertPlainText(QString("[Error]  Before ping, Please init mqtt client.\n"));
        return;
    }
    bool res = mqttClient->requestPing();
    ui->editLog->insertPlainText(QString("[RESULT] PING? %1\n").arg(res));
}


void MainWindow::on_pBtn_ClearLog_clicked()
{
    ui->editLog->clear();
}

